#include "qknxserial.h"
#include <QtSerialPort/QSerialPort>
#include <QDebug>
#include <QString>
#include <unistd.h>
#include <unistd.h>

static QByteArray readBuff;  //存放接收到的串口数据的空间
static QByteArray readBuffClone;

QknxSerial::QknxSerial()
{
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"构造QknxSerial类完成";
}

QknxSerial::~QknxSerial()
{
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"析构QknxSerial类完成";
}

//进行报文过滤
tRDWRBUFF* QknxSerial::knxPacketFilter(tRDWRBUFF* message)
{
    int i = 0;
    int j = 0;
    uchar ucharRecvMessage[COM_BUFF_LEN] = {0};
    
    for(i = 0;i < readBuffClone.size();i++)
    {
        ucharRecvMessage[i] = (uchar)readBuffClone.at(i);
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤前的报文：";
    knxDebugUcharMessage(ucharRecvMessage,readBuffClone.size());
    
    //进行过滤处理并得到通信报文
    int finalMessageNum = 0;
    int messageLen = 0;
    unsigned char finalMessage[MAX_STAND_COMMESSAGE_LEN] = {0x00};
    for(i = 0;i < readBuffClone.size();i++)
    {   
        //进行报文过滤(反馈报文这里暂时也过滤，监听时不需要显示)
        if(ucharRecvMessage[i] == 0xAA && ucharRecvMessage[1 + i] == 0x55 \
                && ucharRecvMessage[2 + i] == 0xA5 && ucharRecvMessage[3 + i] == 0x5A && ucharRecvMessage[5 + i] > 0)
        {
            for(j = 0;j < ucharRecvMessage[5 + i] + 6;j++)
            {
                finalMessage[j] = ucharRecvMessage[i + j];
            }
            finalMessageNum++;
            messageLen = ucharRecvMessage[5 + i];
            message->arrayLen[finalMessageNum - 1] = messageLen + 6;
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤后的报文：";
            knxDebugUcharMessage(finalMessage,messageLen + 6);
        }
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"接收到的报文长度："<<messageLen;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文数量："<<finalMessageNum;
    memcpy(message->message,ucharRecvMessage,readBuffClone.size());
    message->arrayNum = finalMessageNum;
    
    return message;
}

//获取串口接收到的数据
tRDWRBUFF* QknxSerial::knxGetReadComData(QSerialPort* serial,tRDWRBUFF* readComBuff)
{
    if(!readBuffClone.size())
    {
        if(!readBuffClone.size())
        {
            serial->flush();
            readBuffClone.clear();
            readBuffClone = serial->readAll();
            readBuff = readBuffClone;
        }
        if(!readBuffClone.size())
        {
            qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"串口接收缓存空间为空";
            return NULL;
        }
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"接收到的串口数据长度为："<<readBuff.size();
    
    if(readBuffClone.size() > COM_BUFF_LEN)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"大于串口接收缓存大小";
        return NULL;
    }
    
    //报文过滤
    readComBuff = knxPacketFilter(readComBuff);
    
    return readComBuff;
}

//获取校验字节函数
unsigned char QknxSerial::knxGetFramecheck(unsigned char* message,int messageLen)
{
    unsigned char framecheck = 0;
    int i = 0;

    for(i = 0;i < (messageLen - 1);i++)
    {
        framecheck ^= message[i];
    }
    framecheck = ~framecheck;
    qDebug("校验字节：%02X",framecheck);
    
    return  framecheck;
}

//增加报文头
unsigned char* QknxSerial::knxAddMessageHeader(unsigned char* messageNew,unsigned char* messageOld,int messageLen)
{
    uchar header[6] = {0xAA,0x55,0xA5,0x5A,0x30};
    
    header[5] = messageLen;
    memcpy(messageNew,header,6);
    for(int i=0;i < messageLen;i++)
    {
        messageNew[6 + i] = messageOld[i];
    }
    return messageNew;
}

//进行报文头和校验字节校验函数
int QknxSerial::knxJudgeMessageHeadAndFramecheck(unsigned char* message)
{
    //判断报文头
    if(message[0] != 0xAA || message[1] != 0x55 || message[2] != 0xA5 || message[3] != 0x5A)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文头错误";
        return -1;
    }

    //计算并判断校验字节
    unsigned char messageLen = message[5];
    unsigned char framecheck = 0;
    for(int i = 0;i < messageLen - 1;i++)
    {
        framecheck^=message[i + 6];
    }
    framecheck = ~framecheck;
    if(framecheck != message[messageLen + 6 - 1])
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"校验字节错误:";
        qDebug("%02X",framecheck);
        qDebug("%02X",message[messageLen + 6 - 1]);
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文头和校验字节校验正确";

    return 0;    
}

//发送5个字节的反馈报文的函数
void QknxSerial::knxSendFeedbackMessage(QSerialPort *serial,int sendFlag)
{
    unsigned char feedbackMessage[5] = {0xAA,0x55,0xA5,0x5A};

    if(!sendFlag)
        feedbackMessage[4] = 0x00;
    if(1 == sendFlag)
        feedbackMessage[4] = 0xCC;

    serial->write((char*)feedbackMessage,5);
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送反馈报文完成";
}

//等待接收串口信息的函数
QByteArray QknxSerial::knxWaitReadSerial(QSerialPort *serial)
{
    serial->flush();
    readBuff.clear();
    if(serial->waitForReadyRead(WAIT_READ_TIME))  //设置超时阻塞等待接收
    {
        readBuff = serial->readAll();
        while(serial->waitForReadyRead(READ_WAIT_TIME))
        {
            readBuff += serial->readAll();
        }
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读取到的串口数据长度:"<<readBuff.size();
        readBuffClone = readBuff;  //复制一份给readBuffClone用于总线监听和群组监听 
        return readBuff;
    }
    
    return NULL;
}

//判断5个字节的反馈报文的函数
int QknxSerial::knxJudgeFeedbackMessage(int readLen)
{
    uchar res[COM_BUFF_LEN] = {0x00};
    int i = 0;
    
    if(readLen > COM_BUFF_LEN)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过接收缓存区大小";
        return -1;
    }
    
    for(i = 0;i < readLen;i++)
    {
        res[i] = (uchar)readBuff.at(i);
    }
    knxDebugUcharMessage(res,readLen);

    for(i = 0;i < readLen;i++)
    {
        if(0xAA == res[i] && (i + 4) < readLen && 0x55 == (uchar)res[i + 1] && 0xA5 == res[i + 2] \
                && 0x5A == res[i + 3] && 0xCC == res[i + 4])
            return 0;
    }

    return -1;    
}

//判断写数据后的14个字节的回复报文的函数
int QknxSerial::knxJudgeMemoryWriteRespone(int readLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow)
{
    int i = 0;
    int j = 0;
    unsigned char knxResponeMessage[14] = {0x00};

    //进行回复报文信息过滤并将有效报文拷贝出来
    for(i = 0;i < readLen;i++)
    {
        if((unsigned char)readBuff[i] == 0xAA && (i + 13) < readBuff.size() && (unsigned char)readBuff[i + 1] == 0x55 \
                && (unsigned char)readBuff[i + 2] == 0xA5 && (unsigned char)readBuff[i + 3] == 0x5A \
                && (unsigned char)readBuff[i + 5] == 0x08 && (unsigned char)readBuff[i + 6] == 0xB0 \
                && (unsigned char)readBuff[i + 9] == MCPAByteHigh && (unsigned char)readBuff[i + 10] == MCPAByteLow \
                && (unsigned char)readBuff[i + 11] == 0x60)
        {
            for(j =0;j < 14;j++)
                knxResponeMessage[j] = (unsigned char)readBuff[i + j];
        }
    }
    knxDebugUcharMessage(knxResponeMessage,14);
    
    //判断是否过滤到有效报文
    if(0 == knxResponeMessage[5])
    {
        return -1;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"该包数据写入成功："<<((knxResponeMessage[12] & 0x3C) >> 2);

    //判断是IACK还是NIACK
    if(0xC1 == (knxResponeMessage[12] & 0xC3))
    {
        return 0;
    }
    if(0xC3 == (knxResponeMessage[12] & 0xC3))
    {
        return -2;
    }

    return -3;
}


//重发函数（预留）
QByteArray QknxSerial::knxResend(QSerialPort* serial,unsigned char* message,int messageLen)
{
    int resend_Times = 0;
    QByteArray res;

    while(!readBuff.isEmpty())
    {
        if(3 > resend_Times)
        {
            resend_Times++;
            message[4] = 0x31;
            //按照串口封包协议发送指令到串口
            knxDebugUcharMessage(message,messageLen);
            serial->write((char*)message,messageLen);
            if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
            {
                res = knxWaitReadSerial(serial);
                return res;
            }
            else
            {
                return NULL;
            }
        }
        else
        {
            break;
        }
    }

    return NULL;    
}

//解析knx串口报文
tknxMess* QknxSerial::knxunPackStandMessage(unsigned char* comMessage,int messageLen,tknxMess* standMessageUnpackRes)
{
    //获取控制字段，计算优先级
    uchar pri = comMessage[6] & 0x0F;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"优先级："<<pri;
    if((0 != pri) && (8 != pri) && (4 != pri) && (12 != pri))
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未知的优先级";
        return NULL;
    }
    if(0 == pri)
    {
        standMessageUnpackRes->priority = "System";
    }
    if(8 == pri)
    {
        standMessageUnpackRes->priority = "Alarm";
    }
    if(4 == pri)
    {
        standMessageUnpackRes->priority = "High";
    }
    if(12 == pri)
    {
        standMessageUnpackRes->priority = "Low";
    }
    
    //获取并计算源地址
    ushort sourceAddr = comMessage[7]*256 + comMessage[8];
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"sourceAddr:"<<sourceAddr;
    QString sourceAddrStr;
    sourceAddrStr = knxSetPAToString(sourceAddrStr,sourceAddr);
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"源地址："<<sourceAddrStr;
    standMessageUnpackRes->sourceAddr = sourceAddrStr;
    
    //获取并计算目的地址
    int c = (comMessage[11] >> 7);
    QString destAddrStr;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"dest addr type:"<<c;
    if(1 == c)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"目标地址是组地址";
        ushort destAddr = comMessage[9]*256 + comMessage[10];
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"destAddr:"<<destAddr;
        destAddrStr = knxSetGAToString(destAddrStr,destAddr);
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"目标地址："<<destAddrStr;
        standMessageUnpackRes->destAddr = destAddrStr;
    }
    if(!c)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"目标地址是物理地址";
        ushort destAddr = comMessage[9]*256 + comMessage[10];
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"destAddr:"<<destAddr;
        destAddrStr = knxSetPAToString(destAddrStr,destAddr);
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"目标地址："<<destAddrStr;
        standMessageUnpackRes->destAddr = destAddrStr;
    }
    
    //计算路由跳数
    uchar route = (comMessage[11] >> 4) & 7;
    standMessageUnpackRes->route = route;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"路由跳数为:"<<route;
    
    //获取报文类型、DPT以及INFO信息
    tMessageInfo info = {"","",""};
    tMessageInfo* infoP = &info;
    infoP = knxGetMessageTypeAndDataInfo(comMessage,messageLen,infoP);
    if(!infoP)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取报文类型及数据信息失败";
        return NULL;
    }
    standMessageUnpackRes->DPT = infoP->messageDPT;
    standMessageUnpackRes->info = infoP->messageInfo;
    standMessageUnpackRes->messageType = infoP->messageType;
    
    return standMessageUnpackRes;    
}

//获取报文类型及数据信息
tMessageInfo* QknxSerial::knxGetMessageTypeAndDataInfo(uchar* message,int messageLen,tMessageInfo* tInfo)
{   
    if(messageLen <=6)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文长度不符合要求："<<messageLen;
        return NULL;
    }

    //广播帧（指令参考最新版本的“E-KNX通讯协议集整理”）
    if(0x00 == message[9] && 0x00 == message[10] && 0xED == message[11] && 0x03 == message[12] && 0xDE == message[13])
    {
        tInfo->messageType = "writePABySN";
        tInfo->messageInfo = "通过序列号写设备物理地址";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"通过序列号写设备物理地址";
        return tInfo;
    }
    if(0x00 == message[9] && 0x00 == message[10] && 0xE7 == message[11] && 0x03 == message[12] && 0xDC == message[13])
    {
        tInfo->messageType = "readPABySN";
        tInfo->messageInfo = "通过序列号读设备物理地址";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"通过序列号读设备物理地址";
        return tInfo;
    }
    if(0x00 == message[9] && 0x00 == message[10] && 0xEB == message[11] && 0x03 == message[12] && 0xDD == message[13])
    {
        tInfo->messageType = "readPABySN_respone";
        tInfo->messageInfo = "通过序列号读取设备物理地址的回复报文";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"通过序列号读取设备物理地址的回复报文";
        return tInfo;
    }
    if(0x00 == message[9] && 0x00 == message[10] && 0xE8 == message[11] && 0x03 == message[12] && 0xDF == message[13])
    {
        tInfo->messageType = "setProgrammingBySN";
        tInfo->messageInfo = "通过序列号设置编程模式";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"通过序列号设置编程模式";
        return tInfo;
    }
    
    //无连接点对点
    if((message[9] || message[10]) && 0x61 == message[11] && 0x03 == message[12])  //获取设备信息
    {
        if(0x21 == message[13])
        {
            tInfo->messageType = "getDeviceTypeByPA";
            tInfo->messageInfo = "获取设备型号";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取设备型号";
            return tInfo;
        }
        if(0x23 == message[13])
        {
            tInfo->messageType = "getManufacturerByPA";
            tInfo->messageInfo = "获取厂家信息";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取厂家信息";
            return tInfo;
        }
        if(0x25 == message[13])
        {
            tInfo->messageType = "getManufactureDateByPA";
            tInfo->messageInfo = "获取出厂日期";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取出厂日期";
            return tInfo;
        }
        if(0x27 == message[13])
        {
            tInfo->messageType = "MaskVersion";
            tInfo->messageInfo = "获取设备版本号";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取设备版本号";
            return tInfo;
        }
    }
    if((message[9] || message[10]) && 0x61 == message[11] && 0x03 == message[12] && 0x80 == message[13])
    {
        tInfo->messageType = "DeviceRestart";
        tInfo->messageInfo = "设备重启";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备重启";
        return tInfo;
    }
    if((message[9] || message[10]) && 0x65 == message[11] && 0x03 == message[12] && 0xD5 == message[13])
    {
        tInfo->messageType = "readInterOBJValue";
        tInfo->messageInfo = "读接口对象值";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读接口对象值";
        return tInfo;
    }
    if((message[9] || message[10]) && 0x03 == message[12] && 0xD6 == message[13])
    {
        tInfo->messageType = "readInterOBJValue_respone";
        tInfo->messageInfo = "读接口对象值的回复";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读接口对象值的回复";
        return tInfo;
    }
    if((message[9] || message[10]) && 0x65 == message[11] && 0x03 == message[12] && 0xD5 == message[13] && 0x00 == message[14])
    {
        tInfo->messageType = "readDeviceSN";  //读设备序列号，暂时不细分
        tInfo->messageInfo = "读设备序列号";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读设备序列号";
        return tInfo;
    }
    if((message[9] || message[10]) && (0x65 + 6) == message[11] && 0x03 == message[12] && 0xD6 == message[13] && 0x00 == message[14])
    {
        tInfo->messageType = "readDeviceSN_respone";
        tInfo->messageInfo = "读设备序列号的反馈";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读设备序列号的反馈";
        return tInfo;
    }
    
    //连接点对点
    if((message[9] || message[10]) && 0x60 == message[11] && 0x80 == message[12])
    {
        tInfo->messageType = "connectByPA";
        tInfo->messageInfo = "点对点连接";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接";
        return tInfo;
    }
    if((message[9] || message[10]) && 0x60 == message[11] && 0x81 == message[12])
    {
        tInfo->messageType = "disconnectByPA";
        tInfo->messageInfo = "断开点对点连接";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"断开点对点连接";
        return tInfo;
    }
    if((message[9] || message[10]) && 0b01000010 == (message[12] & 0b11000011) && 0b10000000 == (message[13] & 0b11110000))
    {
        tInfo->messageType = "memoryWrite";
        tInfo->messageInfo = "写设备数据区";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写设备数据区";
        return tInfo;
    }
    if((message[9] || message[10]) && 0x60 == message[11])
    {
        if(0b11000001 == (message[12] & 0b11000011))
        {
            tInfo->messageType = "IACK";
            tInfo->messageInfo = "写设备数据区成功";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写设备数据区成功";
            return tInfo;
        }
        if(0b11000011 == (message[12] & 0b11000011))
        {
            tInfo->messageType = "INAK";
            tInfo->messageInfo = "写设备数据区失败";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写设备数据区失败";
            return tInfo;
        }
    }
    if((message[9] || message[10]) && 0x63 == message[11] && 0b01000010 == (message[12] & 0b11000011) && 0 == (message[13] & 0b11110000))
    {
        tInfo->messageType = "memoryRead";
        tInfo->messageInfo = "读设备数据区";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读设备数据区";
        return tInfo;
    }
    if((message[9] || message[10]) && 0b01000010 == (message[12] & 0b11000011) && 0b01000000 == (message[13] & 0b11110000))
    {
        tInfo->messageType = "memoryRead_respone";
        tInfo->messageInfo = "读设备数据区的反馈";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备数据区反馈";
        return tInfo;
    }
    
    //多播帧
    if((message[9] || message[10]) && 0xE1 == message[11] && 0x00 == message[12] && 0x00 == message[13])
    {
        tInfo->messageType = "groupValueRead";
        tInfo->messageInfo = "通过组地址读取通讯对象值";
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"组地址通讯对象数据读取";
        return tInfo;
    }
    if((message[9] || message[10]))
    {
        if(0xE1 == message[11] && 0x00 == message[12] && 0b01000000 == (message[13] & 0b11000000))
        {
            tInfo->messageType = "groupValueRead_respone:dataLen <= 6bit";
            tInfo->messageInfo = QString("通过组地址读通讯对象后的回复数据：$%1").arg(message[13] & 0b00111111);
            tInfo->messageDPT = "原始（直至6bit）";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据小于等于6bit";
            return tInfo;
        }
        if(0xE1 < message[11] && 0x00 == message[12] && 0x40 == message[13])
        {
            tInfo->messageType = "groupValueRead_respone:dataLen > 6bit";
            tInfo->messageInfo = QString("通过组地址读通讯对象后的回复数据：$%1");
            tInfo->messageDPT = QString("%1个字节").arg((message[11] & 0x0F) - 1);
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据大于6bit";
            return tInfo;
        }
        if(0xE1 == message[11] && 0x00 == message[12] && (0x80 == (message[13] & 0xC0)))
        {
            tInfo->messageType = "groupValueWrite:dataLen <= 6bit";
            tInfo->messageInfo = QString("通过组地址写数据：$%1").arg(message[13] & 0b00111111);
            tInfo->messageDPT = "原始（直至6bit）";
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据小于等于6bit的写入群组指令";
            return tInfo;
        }
        if(0xE1 < message[11] && 0x00 == message[12] && 0x80 == message[13])
        {
            tInfo->messageType = "groupValueWrite:dataLen > 6bit";
            tInfo->messageInfo = QString("通过组地址写数据：$%1");
            tInfo->messageDPT = QString("%1个字节").arg((message[11] &0x0F) - 1);
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据大于6bit的写入群组指令";
            return tInfo;
        }
    }
    qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未识别的报文";
    return NULL;
}

//形成knx报文的函数
tSPMess* QknxSerial::knxPackStandMessage(uchar isMessageRepeat,uchar priority,QString sourceAddr,bool destAddrType,QString destAddr,uchar route,uchar dataType,ushort commandType,QString data,tSPMess* packMessage)
{
    //形成控制字段
    uchar controlField = 0;
    if(1 == isMessageRepeat)  //重发
    {
        controlField += 0x90;
    }
    if(0 == isMessageRepeat)  //不重发
    {
        controlField += 0xB0;
    }
    
    if((priority != 0) && (priority != 8) && (priority != 4) && (priority != 12))  //判断优先级
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"错误的优先级数据："<<priority;
        return NULL;
    }
    controlField += priority;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<QString("控制字节：%1").arg(controlField,2,16,QLatin1Char('0'));
    
    //转换并计算源地址高低字节
    uchar sourceAddrArray[2] = {0};
    uchar* sourceAddrArrayPoint = sourceAddrArray;
    sourceAddrArrayPoint = knxGetPATwoByte(sourceAddr,sourceAddrArray);
    if(!sourceAddrArrayPoint)
    {
        return NULL;
    }
    
    //判断目标地址类型并转换目标地址为高低两个字节
    uchar destAddrArray[2] = {0};
    uchar* destAddrArrayPoint = destAddrArray;
    if(1 == destAddrType)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"目标地址为组地址";
        destAddrArrayPoint = knxGetGATwoByte(destAddr,destAddrArray);
        if(!destAddrArrayPoint)
        {
            return NULL;
        }
    }
    if(0 == destAddrType)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"目标地址为物理地址";
        destAddrArrayPoint = knxGetPATwoByte(destAddr,destAddrArray);
        if(!destAddrArrayPoint)
        {
            return NULL;
        }
    }
    
    //计算长度字节值
    uchar length = 0;
    int dataLen = 0;  //数据长度由数据类型决定
    if(dataType < 6)
        dataLen = 1;
    else if(dataType < 11)
    {
        dataLen = dataType - 7 + 2;
        if(dataLen < 2)
            dataLen = 2;
    }
    if(1 == destAddrType)  //长度字节包括目标地址类型，路由计数以及数据长度
        length = 0x80 + (route << 4) + dataLen;
    if(0 == destAddrType)
        length = (route << 4) + dataLen;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"长度字节："<<length;
    
    //计算数据字节(目前使用TP1报文格式且最大支持四个字节的数据处理)
    uchar dataArray[6] = {0};
    uchar* dataArrayPoint = dataArray;
    dataArrayPoint = knxGetDataArray(dataType,commandType,data,dataArrayPoint);
    
    //计算校验字节
    packMessage->message[0] = controlField;
    packMessage->message[1] = sourceAddrArray[0];
    packMessage->message[2] = sourceAddrArray[1];
    packMessage->message[3] = destAddrArray[0];
    packMessage->message[4] = destAddrArray[1];
    packMessage->message[5] = length;
    for(int i = 0;i< (dataLen + 1);i++)
    {
        packMessage->message[6 + i] = dataArray[i];
    }
    packMessage->messageLen = 6 + dataLen + 1;
    uchar checkByte = knxGetFramecheck(packMessage->message,packMessage->messageLen);
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"校验字节："<<checkByte;
    packMessage->message[packMessage->messageLen] = checkByte;
    packMessage->messageLen++;
    
    return packMessage;
}

//获取数据字节(目前仅支持原始数据类型（DPT），且暂时支持到四个字节，暂时未进行扩展，该部分工作量很大)
uchar* QknxSerial::knxGetDataArray(uchar dataType,ushort commandData,QString data,uchar* dataArray)
{
    //通过指令数据确认第一个数据字节
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"指令数据："<<commandData;
    if(10 == commandData)
        dataArray[0] = 0x02;
    else
        dataArray[0] = 0x00;
    
    int value = data.toInt();

    uchar dataByte0 = 0;  //各个字节的值由数据类型和数据值共同决定
    uchar dataByte1 = 0;
    uchar dataByte2 = 0;
    uchar dataByte3 = 0;
    uchar dataByte4 = 0;
    if(dataType < 6)  //当数据类型值为5时表示数据为6位，小于6位的数据特殊处理
    {
        dataByte0 = (uchar)(value & 0x0000003F);
        if(1 == commandData)  //数据的第二个字节的高四位和控制指令有关
            dataArray[1] = 0x40 + dataByte0;
        if((10 == commandData) || (2 == commandData))
            dataArray[1] = 0x80 + dataByte0;
        if(0 == commandData)
            dataArray[1] = 0x00 + dataByte0;
    }
    else
    {
        if(1 == commandData)
            dataArray[1] = 0x40;
        if((10 == commandData) || (2 == commandData))
            dataArray[1] = 0x80;
        if(0 == commandData)
            dataArray[1] = 0x00;
        dataByte1 = (uchar)(value & 0x000000FF);
        dataByte2 = (uchar)(value & 0x0000FF00);
        dataByte3 = (uchar)(value & 0x00FF0000);
        dataByte4 = (uchar)(value & 0xFF000000);
        switch(dataType)
        {
            case 6:
            case 7:
                dataArray[2] = dataByte1;
                break;
            case 8:
                dataArray[2] = dataByte2;
                dataArray[3] = dataByte1;
                break;
            case 9:
                dataArray[2] = dataByte3;
                dataArray[3] = dataByte2;
                dataArray[4] = dataByte1;
                break;
            case 10:
                dataArray[2] = dataByte4;
                dataArray[3] = dataByte3;
                dataArray[4] = dataByte2;
                dataArray[5] = dataByte1;
                break;
            default:
                qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"不支持的数据类型";  //目前先考虑到四个字节
                break;
        }
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据数组："<<dataArray[0]<<" "<<dataArray[1]<<" "<<dataArray[2]<<" "<<dataArray[3]<<" "<<dataArray[4]<<" "<<dataArray[5];

    return dataArray;    
}

//计算设备序列号报文的函数
unsigned char* QknxSerial::knxGetSNMessage(unsigned char* SNSendMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,unsigned char propertyID,unsigned char deviceTypeByteHigh,unsigned char deviceTypeByteLow)
{
    unsigned char SNMessageTmp[18] = {0xAA,0x55,0xA5,0x5A,0x30,0x0D,0xB0,MCPAByteHigh,MCPAByteLow,devicePAByteHigh,devicePAByteLow,0x65,0x03,0xD5,0x00,propertyID,deviceTypeByteHigh,deviceTypeByteLow};
    
    memcpy(SNSendMessage,SNMessageTmp,18);
    SNSendMessage[18] = knxGetFramecheck(SNSendMessage,19);
    knxDebugUcharMessage(SNSendMessage,19);
    
    return SNSendMessage;
}

//获取设备序列号的函数
int QknxSerial::knxSearchDeviceSN(QSerialPort* serial,unsigned char* SNSendMessage,int SNSendMessageLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char snBuff[][6],unsigned char propertyID)
{
    int i,j,k = 0;

    //发送获取设备序列号的报文
    serial->write((char*)SNSendMessage,SNSendMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写序列号报文到串口超时";
        return -1;
    }

    //进行初步处理和判断
    unsigned char ucharRecvMessage[COM_BUFF_LEN] = {0x00};
    if(readBuff.size() >= COM_BUFF_LEN)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过串口接收缓冲区大小";
        return -1;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"收到的来自串口的整体报文长度:"<<readBuff.size();

    for(i = 0;i < readBuff.size();i++)
    {
        ucharRecvMessage[i] = (uchar)readBuff.at(i);
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤前的序列号报文：";
    knxDebugUcharMessage(ucharRecvMessage,readBuff.size());
    int probablyDeviceNum = 0;
    probablyDeviceNum = readBuff.size()/25;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"搜索到的设备数量初步确定为："<<probablyDeviceNum;
    
    //进行过滤处理并得到序列号
    int finalDeviceNum = 0;
    for(i = 0;i < readBuff.size();i++)
    {
        unsigned char finalSNMessage[25] = {0x00};
        
        //进行报文过滤
        if(ucharRecvMessage[i] == 0xAA && (i + 24) < readBuff.size() && ucharRecvMessage[1 + i] == 0x55 \
                && ucharRecvMessage[2 + i] == 0xA5 && ucharRecvMessage[3 + i] == 0x5A\
                && ucharRecvMessage[5 + i] == 0x13 && ucharRecvMessage[6 + i] == 0xB0 \
                && ucharRecvMessage[9 + i] == MCPAByteHigh && ucharRecvMessage[10 + i] == MCPAByteLow \
                && ucharRecvMessage[11 + i] == 0x6B && ucharRecvMessage[12 + i] == 0x03 \
                && ucharRecvMessage[13 + i] == 0xD6 && ucharRecvMessage[14 + i] == 0x00 \
                && ucharRecvMessage[15 + i] == propertyID)
        {
            for(j = 0;j < 25;j++)
            {
                finalSNMessage[j] = ucharRecvMessage[i + j];
            }
            finalDeviceNum++;
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤后的序列号报文：";
            knxDebugUcharMessage(finalSNMessage,25);
        }
        else
            continue;

        //对过滤后的报文的报文头和校验字节进行校验
        int judgeRes = knxJudgeMessageHeadAndFramecheck(finalSNMessage);
        if(judgeRes < 0)
        {
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"SN接收报文校验错误";
            knxSendFeedbackMessage(serial,0);
            continue;
        }
        else
        {
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"SN接收报文检验正确";
            knxSendFeedbackMessage(serial,1);
        }
        
        //获取序列号
        for(k = 0;k < 6;k++)
        {
            snBuff[finalDeviceNum - 1][k] = finalSNMessage[18 + k];
        }
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"序列号:";
        knxDebugUcharMessage(snBuff[finalDeviceNum -1],6);
    }
    
    return finalDeviceNum;    
}

//计算写设备物理地址的广播帧报文
unsigned char* QknxSerial::knxGetWritePAByBroadcastMethod(unsigned char* writeDevicePAMessage, unsigned char MCPAByteHigh, unsigned char MCPAByteLow, unsigned char newPAByteHigh, unsigned char newPAByteLow)
{
    unsigned char writeDevicePAMessageTmp[16] = {0xAA,0x55,0xA5,0x5A,0x30,0x0B,0xB0,MCPAByteHigh,MCPAByteLow,0x00,0x00,0xE3,0x00,0xC0,newPAByteHigh,newPAByteLow};
    
    memcpy(writeDevicePAMessage, writeDevicePAMessageTmp, 16);
    writeDevicePAMessage[16] = knxGetFramecheck(writeDevicePAMessage, 17);
    
    return writeDevicePAMessage;
}

//通过广播方式对处于编程模式的设备写物理地址
int QknxSerial::knxWritePAByBroadcastMethod(QSerialPort *serial, unsigned char *writePAMessage, int writePAMessageLen)
{
    QByteArray readRes;
    
    //发送指令到串口
    serial->write((char*)writePAMessage,writePAMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写物理地址指令发送成功，正在进行反馈报文接收";
        readRes = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写物理地址指令发送超时";
        return -1;
    }

    //接收反馈报文
    if(knxJudgeFeedbackMessage(readRes.size()) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写物理地址不成功";
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"反馈校验完成,写物理地址成功";
    return 0;
}

//计算对于处于编程模式的设备读取物理地址的报文函数
unsigned char* QknxSerial::knxGetReadDevicePAByBroadcastMethod(unsigned char* readDevicePAMessage, unsigned char MCPAByteHigh, unsigned char MCPAByteLow)
{
    unsigned char readDevicePAMessageTmp[14] = {0xAA,0x55,0xA5,0x5A,0x30,0x09,0xB0,MCPAByteHigh,MCPAByteLow,0x00,0x00,0xE1,0x01,0x00};
    
    memcpy(readDevicePAMessage, readDevicePAMessageTmp, 14);
    readDevicePAMessage[14] = knxGetFramecheck(readDevicePAMessage, 15);
    
    return readDevicePAMessage;
}

//获取设备物理地址
int QknxSerial::knxReadDevicePAByBroadcastMethod(QSerialPort* serial,unsigned char* readPAMessage,int readPAMessageLen)
{
    int i,j = 0;
    
    QByteArray readRes;
    //发送获取设备序列号的报文
    serial->write((char*)readPAMessage,readPAMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        readRes = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读物理地址的报文发送到串口超时";
        return -1;
    }

    //进行初步处理和判断
    unsigned char ucharRecvMessage[COM_BUFF_LEN] = {0x00};
    if(readRes.size() >= COM_BUFF_LEN)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过串口接收缓冲区大小";
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"收到的来自串口的整体报文长度:"<<readRes.size();

    for(i = 0;i < readRes.size();i++)
    {
        ucharRecvMessage[i] = (uchar)readRes.at(i);
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤前的读取物理地址的报文：";
    knxDebugUcharMessage(ucharRecvMessage,readRes.size());
    
    //进行回复报文过滤获取有效报文
    unsigned char devicePAInfo[15] = {0x00};
    for(i = 0;i < readBuff.size();i++)
    {
        if(0xAA == ucharRecvMessage[i] && 0x55 == ucharRecvMessage[i + 1] && 0xA5 == ucharRecvMessage[i + 2] \
                && 0x5A == ucharRecvMessage[i +3] && 0xE1 == ucharRecvMessage[11 + i] \
                && 0x01 == ucharRecvMessage[12 + i] && 0x40 == ucharRecvMessage[13 + i])
        {
            for(j = 0;j < 15;j++)
            {
                devicePAInfo[j] = ucharRecvMessage[i + j];
            }
        }
    }
        
    //进行有效报文报文头及字节校验
    int judge_res = knxJudgeMessageHeadAndFramecheck(devicePAInfo);
    if(judge_res < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备物理地址报文校验错误";
        serial->write("0xAA,0x55,0xA5,0x5A,0x00",5);
        return -3;
    }

    //计算物理地址
    int devicePA = devicePAInfo[7]*256 + devicePAInfo[8];
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备物理地址："<<devicePA<<devicePAInfo[7]<<devicePAInfo[8];
    
    return devicePA;
}

//计算设置设备模式的报文函数
unsigned char* QknxSerial::knxGetDeviceModeMessage(unsigned char* deviceModeMessage,unsigned char* sn,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,int deviceModeFlag)
{
    int i = 0;
    unsigned char deviceModeMessageTmp[14] = {0xAA,0x55,0xA5,0x5A,0x30,0x10,0xB0,MCPAByteHigh,MCPAByteLow,0x00,0x00,0xE8,0x03,0xDF};

    memcpy(deviceModeMessage,deviceModeMessageTmp,14);
    if(!deviceModeFlag)
        deviceModeMessage[14] = 0x00;
    if(1 == deviceModeFlag)
        deviceModeMessage[14] = 0x80;
    for(i = 0;i < 6;i++)
    {
        deviceModeMessage[15 + i] = sn[i];
    }
    deviceModeMessage[21] = knxGetFramecheck(deviceModeMessage,22);
    
    return deviceModeMessage;
}

//设置设备模式
int QknxSerial::knxSetDeviceMode(QSerialPort *serial,unsigned char* setDeviceModeMessage,int setDeviceModeMessageLen)
{
    int ret = 0;

    knxDebugUcharMessage(setDeviceModeMessage,setDeviceModeMessageLen);
    serial->write((char*)setDeviceModeMessage,setDeviceModeMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写设置设备模式报文超时";
        return -1;
    }

    ret = knxJudgeFeedbackMessage(readBuff.size());
    if(ret < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设置模式失败";
        return -2;
    }

    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设置模式成功";
    return 0;
}

//物理地址转换函数
QString QknxSerial::knxSetPAToString(QString PAStr,int PA)
{
    PAStr = QString::number(PA >> 12,10);
    PAStr.append(".");
    PAStr.append(QString::number((PA >> 8) & 0x0F,10));
    PAStr.append(".");
    PAStr.append(QString::number(PA & 0xFF,10));
    
    return PAStr;
}

//组地址转换函数
QString QknxSerial::knxSetGAToString(QString GAStr,int GA)
{
    GAStr = QString::number(GA >> 11,10);
    GAStr.append("/");
    GAStr.append(QString::number((GA >> 8) & 0x07,10));
    GAStr.append("/");
    GAStr.append(QString::number(GA & 0xFF,10));
    
    return GAStr;
}

//物理地址字符串（*.*.*，比如0.0.1）转换为两个字节
uchar* QknxSerial::knxGetPATwoByte(QString PAStr,uchar* paArray)
{
    QStringList list1;
    QString fir;
    QString sec;
    QString thr;
    
    //分隔符"."
    if(PAStr.contains(".",Qt::CaseSensitive))
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"分隔符为.";
        list1 = PAStr.split('.');
        fir = list1.at(0);
        sec = list1.at(1);
        thr = list1.at(2);
        paArray[0] = (uchar)((fir.toInt())*16 + sec.toInt());
        paArray[1] = (uchar)thr.toInt();
        QString res = QString("fir:%1,sec:%2,thr:%3,pa0:%4,pa1:%5").arg(fir).arg(sec).arg(thr).arg(paArray[0]).arg(paArray[1]);
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址转换结果："<<res;
        return paArray;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址分隔不符合规范";
    return NULL;
}

//组地址字符串（*/*/*，0/0/1）转换为两个字节
uchar* QknxSerial::knxGetGATwoByte(QString GAStr,uchar* gaArray)
{
    QStringList list1;
    QString fir;
    QString sec;
    QString thr;
    
    //分隔符"/"
    if(GAStr.contains("/",Qt::CaseSensitive))
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"分隔符为/";
        list1 = GAStr.split('/');
        fir = list1.at(0);
        sec = list1.at(1);
        thr = list1.at(2);
        gaArray[0] = (uchar)(((fir.toInt())<<3) + sec.toInt());
        gaArray[1] = (uchar)thr.toInt();
        QString res = QString("fir:%1,sec:%2,thr:%3,ga0:%4,ga1:%5").arg(fir).arg(sec).arg(thr).arg(gaArray[0]).arg(gaArray[1]);
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"组地址转换结果："<<res;
        return gaArray;
    }
    qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"组地址分隔不符合规范";
    return NULL;
}

//debug打印报文
void QknxSerial::knxDebugUcharMessage(unsigned char* ucharMessage,int ucharMessageLen)
{
    QString showSendMessage;
    for(int i = 0;i < ucharMessageLen;i++)
    {
        showSendMessage.append(QString("%1").arg(ucharMessage[i],2,16, QLatin1Char('0')).toUpper());
        showSendMessage.append(" ");
    }

    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文内容："<<showSendMessage;
    return;
}

//转换uchar序列号数组为字符串
QString QknxSerial::knxSNUcharToString(QString SNBuff,unsigned char* SNUchar)
{
    for(int i = 0;i < 6;i++)
    {
        SNBuff.append(QString("%1").arg(SNUchar[i],2,16,QLatin1Char('0')).toUpper());
//        SNBuff.append(" ");  //暂时不加空格
    }
    
    return SNBuff;
}

//序列号转换函数2（QString字符串转化为uchar数组）
int QknxSerial::knxSNQStringToUchar(unsigned char* SNUchar,QString SNBuff)
{
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"要转换的序列号字符串："<<SNBuff<<"大小："<<SNBuff.size();
    if(SNBuff.isEmpty())
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"序列号字符串为空";
        return -1;
    }
    if(SNBuff.size() > 12)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"序列号字符串长度不符合要求";
        return -2;
    }
    
    for(int i = 0;i < 12;i+=2)
    {
        QString tmp;
        tmp.clear();
        tmp = SNBuff[i];
        tmp.append(SNBuff[i + 1]);
        bool ok = true;
        SNUchar[i/2] = (uchar)tmp.toUShort(&ok,16);
    }

    return 0;
}

//计算建立连接和断开连接的报文
unsigned char* QknxSerial::knxGetConOrDisMessage(unsigned char* connectOrDisMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,int connectOrDisFlag)
{
    unsigned char connectOrDisMessageTmp[12] = {0xAA,0x55,0xA5,0x5A,0x30,0x08,0xB0,MCPAByteHigh,MCPAByteLow,devicePAByteHigh,devicePAByteLow,0x60};
    
    memcpy(connectOrDisMessage,connectOrDisMessageTmp,12);
    if(!connectOrDisFlag)
        connectOrDisMessage[12] = 0x80;
    if(1 == connectOrDisFlag)
        connectOrDisMessage[12] = 0x81;
    connectOrDisMessage[13] = knxGetFramecheck(connectOrDisMessage,14);
    
    return connectOrDisMessage;
}

//建立连接和断开连接函数
int QknxSerial::knxConnectOrDisconnect(QSerialPort* serial,unsigned char* connectOrDisMessage,int connectOrDisMessageLen)
{
    QByteArray readRes;
    
    //发送指令到串口
    serial->write((char*)connectOrDisMessage,connectOrDisMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        readRes = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"建立点对点连接/断开连接指令发送超时";
        return -1;
    }

    //接收反馈报文
    if(knxJudgeFeedbackMessage(readRes.size()) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"建立点对点连接/断开连接不成功";
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"建立点对点连接/断开连接成功";

    return 0;
}

//计算重启设备的报文
unsigned char* QknxSerial::knxGetRestartMessage(unsigned char* restartMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow)
{
    unsigned char restartMessageTmp[14] = {0xAA,0x55,0xA5,0x5A,0x30,0x09,0xB0,MCPAByteHigh,MCPAByteLow,devicePAByteHigh,devicePAByteLow,0x61,0x03,0x80};
    
    memcpy(restartMessage,restartMessageTmp,14);
    restartMessage[14] = knxGetFramecheck(restartMessage,15);
    
    return restartMessage;
}

//重启设备函数
int QknxSerial::knxRestart(QSerialPort* serial,unsigned char* restartMessage,int restartMessageLen)
{
    QByteArray readRes;
    
    //发送指令到串口
    serial->write((char*)restartMessage,restartMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        readRes = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"重启设置指令发送超时";
        return -1;
    }

    //接收反馈报文
    if(knxJudgeFeedbackMessage(readRes.size()) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"重启设备不成功";
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"重启设备成功";

    return 0;
}

//计算根据序列号写物理地址的报文
unsigned char* QknxSerial::knxGetWritePAMessage(unsigned char* writePAMessage,unsigned char* sn,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow)
{
    unsigned char writePAMessageTmp[14] = {0xAA,0x55,0xA5,0x5A,0x30,0x15,0xB0,MCPAByteHigh,MCPAByteLow,0x00,0x00,0xED,0x03,0xDE};
    
    memcpy(writePAMessage,writePAMessageTmp,14);
    for(int i = 0;i < 6;i++)
    {
        writePAMessage[14 + i] = sn[i];
    }
    writePAMessage[20] = devicePAByteHigh;
    writePAMessage[21] = devicePAByteLow;
    writePAMessage[22] = 0x00;
    writePAMessage[23] = 0x00;
    writePAMessage[24] = 0x00;
    writePAMessage[25] = 0x00;
    writePAMessage[26] = knxGetFramecheck(writePAMessage,27);
    
    return writePAMessage;
}

//根据序列号写物理地址函数
int QknxSerial::knxWritePAAccordingToSN(QSerialPort* serial,unsigned char* writePAMessage,int writePAMessageLen)
{
    QByteArray readRes;
    
    //发送指令到串口
    serial->write((char*)writePAMessage,writePAMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写物理地址指令发送成功，正在进行反馈报文接收";
        readRes = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写物理地址指令发送超时";
        return -1;
    }

    //接收反馈报文
    if(knxJudgeFeedbackMessage(readRes.size()) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写物理地址不成功";
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"反馈校验完成,写物理地址成功";

    return 0;    
}

//计算获取设备信息的报文
unsigned char* QknxSerial::knxGetDeviceInfoMessage(unsigned char* getDeviceInfoMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,int getDeviceInfoFlag)
{
    unsigned char getDeviceInfoMessageTmp[13] = {0xAA,0x55,0xA5,0x5A,0x30,0x09,0xB0,MCPAByteHigh,MCPAByteLow,devicePAByteHigh,devicePAByteLow,0x61,0x03};
    
    memcpy(getDeviceInfoMessage,getDeviceInfoMessageTmp,13);
    if(1 == getDeviceInfoFlag)
        getDeviceInfoMessage[13] = 0x21;
    if(2 == getDeviceInfoFlag)
        getDeviceInfoMessage[13] = 0x23;
    if(3 == getDeviceInfoFlag)
        getDeviceInfoMessage[13] = 0x25;
    if(4 == getDeviceInfoFlag)
        getDeviceInfoMessage[13] = 0x27;
    getDeviceInfoMessage[14] = knxGetFramecheck(getDeviceInfoMessage,15);
    
    return getDeviceInfoMessage;
}

//获取设备信息的函数
QString QknxSerial::knxGetDeviceInfo(QSerialPort* serial,QString deviceInfo,unsigned char* getDeviceInfoMessage,int getDeviceInfoMessageLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,int getDeviceInfoFlag)
{
    QByteArray readDeviceInfoRes;
    int i = 0;
    int j = 0;
    
    //发送指令到串口
    serial->write((char*)getDeviceInfoMessage,getDeviceInfoMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        readDeviceInfoRes = knxWaitReadSerial(serial);
    }
    else
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写获取设备信息的指令发送超时:"<<getDeviceInfoFlag;
        return NULL;
    }    
        
    //进行回复报文初步处理
    unsigned char ucharReadDeviceInfoRes[COM_BUFF_LEN] = {0x00};
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文长度:"<<readDeviceInfoRes.size();
    if(readDeviceInfoRes.size() > COM_BUFF_LEN)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过缓冲区大小";
        return NULL;
    }
    for(i = 0;i < readDeviceInfoRes.size();i++)
    {
        ucharReadDeviceInfoRes[i] = (uchar)readDeviceInfoRes.at(i);
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未过滤的设备信息接收报文:";
    knxDebugUcharMessage(ucharReadDeviceInfoRes,readDeviceInfoRes.size());

    //进行回复报文过滤获取有效报文长度
    int deviceInfoRecvMessageLen = 0;
    unsigned char deviceInfoType = 0;
    if(1 == getDeviceInfoFlag)
        deviceInfoType = 0x61;
    if(2 == getDeviceInfoFlag)
        deviceInfoType = 0x63;
    if(3 == getDeviceInfoFlag)
        deviceInfoType = 0x65;
    if(4 == getDeviceInfoFlag)
        deviceInfoType = 0x67;
    for(i = 0;i < readDeviceInfoRes.size();i++)
    {
        if(0xAA == ucharReadDeviceInfoRes[i] && 0x55 == ucharReadDeviceInfoRes[i + 1] && 0xA5 == ucharReadDeviceInfoRes[i + 2] \
                && 0x5A == ucharReadDeviceInfoRes[i +3] && devicePAByteHigh == ucharReadDeviceInfoRes[i + 7] \
                && devicePAByteLow == ucharReadDeviceInfoRes[i + 8] && MCPAByteHigh == ucharReadDeviceInfoRes[i + 9] \
                && MCPAByteLow == ucharReadDeviceInfoRes[i + 10] && 0x03 == ucharReadDeviceInfoRes[12 + i] \
                && deviceInfoType == ucharReadDeviceInfoRes[13 + i])
        {
            deviceInfoRecvMessageLen = ucharReadDeviceInfoRes[5 + i];
        }
    }
    if(0 == deviceInfoRecvMessageLen)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未获取到设备信息有效报文";
        return NULL;
    }

    //拷贝出来有效报文
    unsigned char deviceInfoFinalMessage[29] = {0x00};
    for(i = 0;i < readDeviceInfoRes.size();i++)
    {
        if(0xAA == ucharReadDeviceInfoRes[i] && 0x55 == ucharReadDeviceInfoRes[i + 1] && 0xA5 == ucharReadDeviceInfoRes[i + 2] \
                && 0x5A == ucharReadDeviceInfoRes[i +3] && devicePAByteHigh == ucharReadDeviceInfoRes[i + 7] \
                && devicePAByteLow == ucharReadDeviceInfoRes[i + 8] && MCPAByteHigh == ucharReadDeviceInfoRes[i + 9] \
                && MCPAByteLow == ucharReadDeviceInfoRes[i + 10] && 0x03 == ucharReadDeviceInfoRes[12 + i] \
                && deviceInfoType == ucharReadDeviceInfoRes[13 + i])
        {
            for(j = 0;j < (deviceInfoRecvMessageLen + 6);j++)
            {
                deviceInfoFinalMessage[j] = ucharReadDeviceInfoRes[i + j];
            }
        }
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤后的有效设备信息报文：";
    knxDebugUcharMessage(deviceInfoFinalMessage,deviceInfoRecvMessageLen + 6);
        
    //进行有效报文报文头及字节校验
    int judge_res = knxJudgeMessageHeadAndFramecheck(deviceInfoFinalMessage);
    if(judge_res < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备信息报文校验错误";
        serial->write("0xAA,0x55,0xA5,0x5A,0x00",5);
        return NULL;
    }

    //获取报文中的设备信息
    uchar deviceInfoLen = deviceInfoFinalMessage[11] - 0x61;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备信息长度:"<<deviceInfoLen;
    if(14 < deviceInfoLen)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过设备信息存储长度";
        return NULL;
    }
    for(i = 0;i < deviceInfoLen;i++)
    {
//        deviceInfo.append(QString("%1").arg(deviceInfoFinalMessage[14 + i],2,16,QLatin1Char('0')).toUpper());
        deviceInfo[i] = deviceInfoFinalMessage[14 + i];
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备信息："<<deviceInfo;
    
    return deviceInfo;
}

//计算获取设备模式和物理地址的报文
unsigned char* QknxSerial::knxGetDeviceModeAndPAMessage(unsigned char* getDeviceModeAndPAMessage,unsigned char* sn,unsigned char MCPAByteHigh,unsigned char MCPAByteLow)
{
    unsigned char getDeviceModeAndPAMessageTmp[14] = {0xAA,0x55,0xA5,0x5A,0x30,0x0F,0xB0,MCPAByteHigh,MCPAByteLow,0x00,0x00,0xE7,0x03,0xDC};
    
    memcpy(getDeviceModeAndPAMessage,getDeviceModeAndPAMessageTmp,14);
    int i = 0;
    for(i = 0;i < 6;i++)
    {
        getDeviceModeAndPAMessage[14 + i] = sn[i];
    }
    getDeviceModeAndPAMessage[20] = knxGetFramecheck(getDeviceModeAndPAMessage,21);
    
    return getDeviceModeAndPAMessage;
}

//获取设备模式和物理地址
int QknxSerial::knxGetDeviceModeAndPA(QSerialPort* serial,unsigned char* getDeviceModeAndPAMessage,int getDeviceModeAndPAMessageLen,int getDeviceModeAndPAFlag)
{
    QByteArray readDeviceModeAndPARes;
    int i = 0;
    int j = 0;
    
    //发送指令到串口
    serial->write((char*)getDeviceModeAndPAMessage,getDeviceModeAndPAMessageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        readDeviceModeAndPARes = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写读取设备序列号和设备模式的指令发送超时:"<<getDeviceModeAndPAFlag;
        return -1;
    }    
        
    //进行回复报文初步处理
    unsigned char ucharReadDeviceModeAndPARes[COM_BUFF_LEN] = {0x00};
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文长度:"<<readDeviceModeAndPARes.size();
    if(readDeviceModeAndPARes.size() > COM_BUFF_LEN)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过缓冲区大小";
        return -2;
    }
    for(i = 0;i < readDeviceModeAndPARes.size();i++)
    {
        ucharReadDeviceModeAndPARes[i] = (uchar)readDeviceModeAndPARes.at(i);
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未过滤的获取设备模式和物理地址的接收报文：";
    knxDebugUcharMessage(ucharReadDeviceModeAndPARes,readDeviceModeAndPARes.size());
    
    //进行报文过滤拷贝出有效报文
    unsigned char finalReadDeviceModeAndPAMessage[25] = {0x00};
    for(i = 0;i < readDeviceModeAndPARes.size();i++)
    {
        if(0xAA == ucharReadDeviceModeAndPARes[i] && (i + 24) < readDeviceModeAndPARes.size() && 0x55 == ucharReadDeviceModeAndPARes[i + 1] \
                && 0xA5 == ucharReadDeviceModeAndPARes[i + 2] && 0x5A == ucharReadDeviceModeAndPARes[i + 3] && 0x13 == ucharReadDeviceModeAndPARes[i + 5] \
                && 0x00 == ucharReadDeviceModeAndPARes[i + 9] && 0x00 == ucharReadDeviceModeAndPARes[i + 10] && 0xEB == ucharReadDeviceModeAndPARes[i + 11] \
                && 0x03 == ucharReadDeviceModeAndPARes[i + 12] && 0xDD == ucharReadDeviceModeAndPARes[i + 13])
        {
            for(j = 0;j < 25;j++)
            {
                finalReadDeviceModeAndPAMessage[j] = ucharReadDeviceModeAndPARes[i + j];
            }
        }
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"过滤后的获取设备模式和物理地址接收报文：";
    knxDebugUcharMessage(finalReadDeviceModeAndPAMessage,25);
    
    if(knxJudgeMessageHeadAndFramecheck(finalReadDeviceModeAndPAMessage) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未获取到有效报文";
        return -3;
    }
    
    //根据flag值判断要返回物理地址还是设备模式
    if(0 == getDeviceModeAndPAFlag)
    {
        int PA = 0;
        PA = finalReadDeviceModeAndPAMessage[20]*256 + finalReadDeviceModeAndPAMessage[21];
        return PA;
    }
    if(1 == getDeviceModeAndPAFlag)
    {
        int modeValue = 0;
        modeValue = finalReadDeviceModeAndPAMessage[22];
        return modeValue;
    }
    qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"flag值错误";
    return -4;
}

static char deviceTypeList[DEVICE_TYPE_NUM][14] = {"SSA12.1.1","PMS4.1.1","TPPM1.1.1","TPFH1.1.1"};  //设备型号列表，目前只有这几种，以后会进行变化
//判断设备型号和模式
int QknxSerial::knxJudgeDeviceTypeAndMode(int mode,QString deviceType)
{
    if(0x80 != mode)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"该设备不处于编程模式:"<<mode;
        return -1;
    }
    
    for(int i = 0;i < DEVICE_TYPE_NUM;i++)
    {
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<QString(deviceTypeList[i]);
        if(deviceType == QString(deviceTypeList[i]))
        {
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备型号存在："<<deviceType<<"---"<<QString(deviceTypeList[i]);
            return 0;
        }
    }
    qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备型号不存在"<<deviceType;

    return -2;
}

//写数据函数
int QknxSerial::knxWriteData(QSerialPort* serial,unsigned char* message,int messageLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow)
{
    QByteArray readWriteDataResendMessage;
    
    serial->write((char*)message,messageLen);
    if(serial->waitForBytesWritten(WAIT_WRITE_TIME))
    {
        readWriteDataResendMessage = knxWaitReadSerial(serial);
    }
    else
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写数据的指令发送超时";
        return -1;
    }

    //进行反馈报文检验
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"报文长度:"<<readWriteDataResendMessage.size();
    if(readWriteDataResendMessage.size() > COM_BUFF_LEN)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"超过缓冲区大小";
        return -2;
    }
    if(knxJudgeMemoryWriteRespone(readWriteDataResendMessage.size(),MCPAByteHigh,MCPAByteLow) < 0)
    {
        return -3;
    }

    return 0;
}

//发送表格信息
int QknxSerial::knxSendTableUseStandardFrame(QSerialPort* serial,unsigned char* tableData,int dataLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,\
                                    unsigned char devicePAByteHigh,unsigned char devicePAByteLow,unsigned short eepromAddressBegin)
{
//    int messageLen = 0;
    int ret = 0;
    int i =0;
    
    //计算数据需要发送的报文的条数和最后一次可能出现的小于12字节的数据的长度
    int messageNum = 0;
    int lastMessageLen = 0;
    if(dataLen <= 12)
        messageNum = 1;
    else if(dataLen%12)
    {
        messageNum = dataLen/12 + 1;
        lastMessageLen = dataLen%12;
    }
    else if(!(dataLen%12))
        messageNum = dataLen/12;
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送报文的条数为:"<<messageNum<<"最后一条数据的长度为:"<<lastMessageLen;

    //发送报文并校验回复报文（按上述结果分三种情况处理）
    uchar message[29] = {0xAA,0x55,0xA5,0x5A,0x30,0x0C,0xB0,MCPAByteHigh,MCPAByteLow,devicePAByteHigh,devicePAByteLow,0x64,0x42,0x81};
    uchar* messagePoint = message;
    //第一种情况，只有一条报文
    if(1 == messageNum)
    {
        //形成报文
        messagePoint+=16;
        message[5] = (uchar)(dataLen + 11);
        message[11] = (uchar)(dataLen + 0x63);
        message[13] = (uchar)(dataLen + 0x80);
        message[14] = (uchar)(eepromAddressBegin >> 8);
        message[15] = (uchar)(eepromAddressBegin & 0xFF);
        memcpy(messagePoint,tableData,dataLen);
        message[16 + dataLen] = knxGetFramecheck(message,17 + dataLen);
        //发送报文
        ret = knxWriteData(serial,message,17 + dataLen,MCPAByteHigh,MCPAByteLow);
        if(ret < 0)
        {
            qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"表格数据发送失败，错误码："<<ret;
            return -1;
        }
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发表格数据成功";
    }
    //第二种情况，多条报文，但最后一条报文正好为12个字节数据
    if(messageNum > 1 && !lastMessageLen)
    {
        for(i = 0;i < messageNum;i++)
        {
            //形成报文
            messagePoint = message;
            messagePoint+=16;
            message[5] = 0x17;
            message[11] = 0x6F;
            message[13] = 0x8C;
            message[14] = (uchar)((eepromAddressBegin + i*12) >> 8);
            message[15] = (uchar)((eepromAddressBegin +i*12) & 0xFF);
            memcpy(messagePoint,tableData + i*12,12);
            message[28] = knxGetFramecheck(message,29);
            //发送报文
            ret = knxWriteData(serial,message,29,MCPAByteHigh,MCPAByteLow);
            if(ret < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"表格数据发送错误，第"<<i<<"条，"<<"错误码："<<ret;
                return -1;
            }
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发表格数据成功，第"<<i<<"条";
        }
    }
    //第三种情况，多条报文而且最后一条小于12个字节
    if(messageNum > 1 && lastMessageLen)
    {
        for(i = 0;i < messageNum;i++)
        {
            //形成报文
            messagePoint = message;
            messagePoint+=16;
            if(i != (messageNum - 1))
            {
                message[5] = 0x17;
                message[11] = 0x6F;
                message[13] = 0x8C;
                message[14] = (uchar)((eepromAddressBegin + i*12) >> 8);
                message[15] = (uchar)((eepromAddressBegin +i*12) & 0xFF);
                memcpy(messagePoint,tableData + i*12,12);
                message[28] = knxGetFramecheck(message,29);
                //发送报文
                ret = knxWriteData(serial,message,29,MCPAByteHigh,MCPAByteLow);
                if(ret < 0)
                {
                    qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"表格数据发送错误，第"<<i<<"条"<<"，错误码"<<ret;
                    return -1;
                }
                qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发表格成功，第"<<i<<"条";
//                messageLen = 29;  //用于重发机制时使用，暂时预留
            }
            else
            {
                message[5] = (uchar)(lastMessageLen + 11);
                message[11] = (uchar)(0x60 + lastMessageLen + 3);
                message[13] = (uchar)(0x80 + lastMessageLen);
                message[14] = (uchar)((eepromAddressBegin + i*12) >> 8);
                message[15] = (uchar)((eepromAddressBegin + i* 12) & 0xFF);
                memcpy(messagePoint,tableData + i*12,lastMessageLen);
                message[16 + lastMessageLen] = knxGetFramecheck(message,17 + lastMessageLen);
                //发送报文
                ret = knxWriteData(serial,message,17 + lastMessageLen,MCPAByteHigh,MCPAByteLow);
                if(ret < 0)
                {
                    qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"表格数据发送错误，第"<<i<<"条，错误码："<<ret;
                    return -2;
                }
                qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发表格数据成功，第"<<i<<"条";
//                messageLen = 17 + lastMessageLen;  //用于重发机制时使用，暂时预留
            }
        }
    }
    return 0;
}
